/*******************************************************************************
 * Copyright (c) 2025-08-06 @author <a href="mailto:iffiff1@gmail.com">Tyler Chen</a>.
 * All rights reserved.
 *
 * Contributors:
 *     <a href="mailto:iffiff1@gmail.com">Tyler Chen</a> - initial API and implementation.
 ******************************************************************************/
package org.iff.util.llm.glm;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

/**
 * 对话消息
 * <pre>
 * {
 *     "model": "glm-4.5",
 *     "do_sample": true,
 *     "stream": false,
 *     "thinking": {
 *         "type": "enabled"
 *     },
 *     "temperature": 0.6,
 *     "top_p": 0.95,
 *     "response_format": {
 *         "type": "text"
 *     },
 *     "messages": [
 *         {
 *             "role": "user",
 *             "content": "test"
 *         }
 *     ],
 *     "max_tokens": 11,
 *     "tools": [
 *         {
 *             "type": "function",
 *             "function": {
 *                 "name": "test",
 *                 "description": "test"
 *             }
 *         }
 *     ],
 *     "tool_choice": "auto",
 *     "user_id": "testest",
 *     "stop": [
 *         "aa",
 *         "bb"
 *     ]
 * }
 * </pre>
 *
 * @author <a href="mailto:iffiff1@gmail.com">Tyler Chen</a>
 * @since 2025-08-06
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class TextMessage {
    public static final String ROLE_USER = "user";
    public static final String ROLE_SYSTEM = "system";
    public static final String ROLE_ASSISTANT = "assistant";
    public static final String ROLE_TOOL = "tool";

    @JsonProperty("model")
    private String model;
    @JsonProperty("messages")
    private List<Messages> messages;
    @JsonProperty("request_id")
    private String requestId;
    @JsonProperty("do_sample")
    private boolean doSample = true;
    @JsonProperty("stream")
    private boolean stream;
    @JsonProperty("thinking")
    private Thinking thinking;
    @JsonProperty("temperature")
    private Double temperature;
    @JsonProperty("top_p")
    private Double topP;
    @JsonProperty("max_tokens")
    private Integer maxTokens;
    @JsonProperty("tools")
    private List<Tool> tools;
    /**
     * 控制模型如何选择工具。 用于控制模型选择调用哪个函数的方式，仅在工具类型为function时补充。默认auto且仅支持auto。
     * Available options: auto
     */
    @JsonProperty("tool_choice")
    private String toolChoice;
    /**
     * 终端用户的唯一标识符。ID长度要求：最少6个字符，最多128个字符，建议使用不包含敏感信息的唯一标识。
     */
    @JsonProperty("user_id")
    private String userId;
    @JsonProperty("stop")
    private List<String> stop;
    @JsonProperty("response_format")
    private ResponseFormat responseFormat;

    public static TextMessage of() {
        return new TextMessage();
    }

    public TextMessage model(String model) {
        this.model = model;
        return this;
    }

    public TextMessage message(String role, String content) {
        if (this.messages == null) {
            this.messages = new ArrayList<>();
        }
        this.messages.add(Messages.builder().role(role).content(content).build());
        return this;
    }

    public TextMessage requestId(String requestId) {
        this.requestId = requestId;
        return this;
    }

    public TextMessage doSample(boolean doSample) {
        this.doSample = doSample;
        return this;
    }

    public TextMessage stream(boolean stream) {
        this.stream = stream;
        return this;
    }

    public TextMessage temperature(Double temperature) {
        this.temperature = temperature;
        return this;
    }

    public TextMessage topP(Double topP) {
        this.topP = topP;
        return this;
    }

    public TextMessage maxTokens(Integer maxTokens) {
        this.maxTokens = maxTokens;
        return this;
    }

    public TextMessage tool(String name, String description, Object parameters) {
        if (this.tools == null) {
            this.tools = new ArrayList<>();
        }
        this.tools.add(Tool.builder().function(CallFunction.builder().name(name).description(description).parameters(parameters).build()).build());
        return this;
    }

    public TextMessage toolChoice(String toolChoice) {
        this.toolChoice = toolChoice;
        return this;
    }

    public TextMessage userId(String userId) {
        this.userId = userId;
        return this;
    }

    public TextMessage stop(List<String> stop) {
        if (this.stop == null) {
            this.stop = new ArrayList<>();
        }
        stop = stop == null ? new ArrayList<>() : stop;
        for (String s : stop) {
            this.stop.add(s);
        }
        return this;
    }

    /**
     * 输出格式类型：text表示普通文本输出，json_object表示JSON格式输出
     * Available options: text, json_object
     */
    public TextMessage responseFormat(String type) {
        this.responseFormat = ResponseFormat.builder().type(type).build();
        return this;
    }

    /**
     * 是否开启思维链, 默认: enabled
     * Available options: enabled, disabled
     */
    public TextMessage thinking(String type) {
        this.thinking = Thinking.builder().type(type).build();
        return this;
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class Messages {
        @JsonProperty("role")
        private String role;
        @JsonProperty("content")
        private String content;
        /**
         * role=tool: 指示此消息对应的工具调用 ID
         */
        @JsonProperty("tool_call_id")
        private String toolCallId;
        /**
         * role=assistant: 指示此消息对应的工具调用 ID
         */
        @JsonProperty("tool_calls")
        private List<ToolCall> toolCalls;
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class ToolCall {
        /**
         * 工具调用ID
         */
        @JsonProperty("id")
        private String id;
        /**
         * 工具类型，支持web_search、retrieval、function
         */
        @JsonProperty("type")
        private String type;
        /**
         * 函数调用信息，当type为function时不为空
         */
        @JsonProperty("type")
        private CallFunction function;
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class CallFunction {
        @JsonProperty("name")
        private String name;
        @JsonProperty("description")
        private String description;
        @JsonProperty("parameters")
        private Object parameters;
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class Tool {
        /**
         * Available options: function
         */
        @JsonProperty("type")
        private String type = "function";
        @JsonProperty("type")
        private CallFunction function;
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class Thinking {
        /**
         * 是否开启思维链, 默认: enabled
         * Available options: enabled, disabled
         */
        @JsonProperty("type")
        private String type = "enabled";
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class ResponseFormat {
        /**
         * 输出格式类型：text表示普通文本输出，json_object表示JSON格式输出
         * Available options: text, json_object
         */
        @JsonProperty("type")
        private String type = "text";
    }
}
